<?php
/**
 *+------------------
 * Lflow
 *+------------------
 * Copyright (c) 2023~2030 gitee.com/liu_guan_qing All rights reserved.本版权不可删除，侵权必究
 *+------------------
 * Author: Mr.April(405784684@qq.com)
 *+------------------
 */
declare (strict_types=1);

namespace lflow\parser;

use lflow\model\NodeModel;
use lflow\model\TransitionModel;

/**
 * 抽象节点解析类 完成通用的属性、变迁解析
 *
 * @author Mr.April
 * @since  1.0
 */
abstract class AbstractNodeParser implements NodeParser
{
    /**
     * 模型对象
     *
     * @var \lflow\model\NodeModel
     */
    protected NodeModel $model;

    /**
     * 实现NodeParser接口的parse函数
     * 由子类产生各自的模型对象，设置常用的名称属性，并且解析子节点transition，构造TransitionModel模型对象
     */
    public function parse(object $workflow, ?object $nodes): void
    {
        $properties  = $nodes->properties ?? (object)[];
        $this->model = $this->newModel();
        $this->model->setName($nodes->{NodeParser::ATTR_NAME} ?? '');
        $this->model->setDisplayName($nodes->text->value ?? '');
        $this->model->setPreInterceptors($properties->{NodeParser::ATTR_PREINTERCEPTORS} ?? '');
        $this->model->setPostInterceptors($properties->{NodeParser::ATTR_POSTINTERCEPTORS} ?? '');
        $edgesList = $workflow->edges ?? (object)[];
        foreach ($edgesList as $edges) {
            if ($nodes->{NodeParser::ATTR_NAME} === $edges->{NodeParser::EDGES_SOURCENODEID}) {
                $transition = new TransitionModel();
                $transition->setName($edges->{NodeParser::ATTR_NAME} ?? '');
                $transition->setDisplayName($edges->text->value ?? '');
                $transition->setTo($edges->{NodeParser::EDGES_TARGETNODEID} ?? '');
                $transition->setExpr($edges->properties->{NodeParser::ATTR_EXPR} ?? '');
                $transition->setSource($this->model);
                $outputList   = $this->model->getOutputs();
                $outputList[] = $transition;
                $this->model->setOutputs($outputList);
                $this->parseNode($this->model, $nodes);
            }
        }
    }

    /**
     * 子类可覆盖此方法，完成特定的解析
     *
     * @param \lflow\model\NodeModel $model
     * @param object|null            $nodes
     */
    protected function parseNode(NodeModel $model, ?object $nodes): void
    {
    }

    /**
     * 抽象方法，由子类产生各自的模型对象
     *
     * @return \lflow\model\NodeModel
     */
    protected abstract function newModel(): NodeModel;

    /**
     * 返回模型对象
     *
     * @return \lflow\model\NodeModel
     */
    public function getModel(): NodeModel
    {
        return $this->model;
    }
}
